#!/bin/bash
#
# Copyright (c) Authors: http://www.armbian.com/authors
#
# Tool to transfer the rootfs of an already running Armbian installation from SD card
# to NAND, eMMC, SATA or USB storage. In case of eMMC it's also possible to transfer
# the bootloader to eMMC in a single step so from then on running without SD card is
# possible.

# Import:
# DIR: path to u-boot directory
# write_uboot_platform: function to write u-boot to a block device
[[ -f /usr/lib/u-boot/platform_install.sh ]] && source /usr/lib/u-boot/platform_install.sh

# script configuration
CWD="/usr/lib/nand-sata-install"
EX_LIST="${CWD}/exclude.txt"
[ -f /etc/default/openmediavault ] && echo '/srv/*' >>"${EX_LIST}"
nanddevice="/dev/nand"
logfile="/var/log/nand-sata-install.log"

# read in board info
[[ -f /etc/armbian-release ]] && source /etc/armbian-release
backtitle="Armbian for $BOARD_NAME install script, http://www.armbian.com"
title="NAND, eMMC, SATA and USB Armbian installer v${VERSION}"

# exception
if grep -q 'sun4i' /proc/cpuinfo; then DEVICE_TYPE="a10";
elif grep -q 'sun5i' /proc/cpuinfo; then DEVICE_TYPE="a13";
else DEVICE_TYPE="a20"; fi
BOOTLOADER="${CWD}/${DEVICE_TYPE}/bootloader"

#recognize_root
root_uuid=$(sed -e 's/^.*root=//' -e 's/ .*$//' < /proc/cmdline)
root_partition=$(blkid | tr -d '":' | grep ${root_uuid} | awk '{print $1}')
root_partition_device="${root_partition::-2}"

# find targets: NAND, EMMC, SATA, SPI
[[ -b /dev/nand ]] && nandcheck=$(ls -d -1 /dev/nand* | grep -w 'nand' | awk '{print $NF}');
emmccheck=$(ls -d -1 /dev/mmcblk* | grep -w 'mmcblk[0-9]' | grep -v "$root_partition_device");
satacheck=$(grep 'sd' /proc/partitions | awk '{print $NF}')
spicheck=$(grep 'mtd' /proc/partitions | awk '{print $NF}')

# define makefs and mount options
declare -A mkopts mountopts
mkopts[ext2]='-qF'
mkopts[ext3]='-qF'
mkopts[ext4]='-qF'
mkopts[btrfs]='-f'

mountopts[ext2]='defaults,noatime,nodiratime,commit=600,errors=remount-ro,x-gvfs-hide	0	1'
mountopts[ext3]='defaults,noatime,nodiratime,commit=600,errors=remount-ro,x-gvfs-hide	0	1'
mountopts[ext4]='defaults,noatime,nodiratime,commit=600,errors=remount-ro,x-gvfs-hide	0	1'
mountopts[btrfs]='defaults,noatime,nodiratime,commit=600,compress=lzo,x-gvfs-hide			0	2'

# Create boot and root file system $1 = boot, $2 = root (Example: create_armbian "/dev/nand1" "/dev/sda3")
create_armbian()
{
	# create mount points, mount and clean
	TempDir=$(mktemp -d /mnt/${0##*/}.XXXXXX || exit 1)
	sync &&	mkdir -p ${TempDir}/bootfs ${TempDir}/rootfs
	if [[ $eMMCFilesystemChoosen == "btrfs" ]]; then
		[[ -n $1 ]] && mount ${1::-1}"1" ${TempDir}/bootfs
		[[ -n $2 ]] && ( mount -o compress-force=zlib $2 ${TempDir}/rootfs || mount $2 ${TempDir}/rootfs )
	else
		[[ -n $2 ]] && ( mount -o compress-force=zlib $2 ${TempDir}/rootfs || mount $2 ${TempDir}/rootfs )
		[[ -n $1 && $1 != "spi" ]] && mount $1 ${TempDir}/bootfs
	fi
	rm -rf ${TempDir}/bootfs/* ${TempDir}/rootfs/*

	# sata root part
	# UUID=xxx...
	satauuid=$(blkid -o export $2 | grep -w UUID)

	# SD card boot part -- wrong since more than one entry on various platforms
	# UUID=xxx...
	sduuid=$(blkid -o export /dev/mmcblk*p1 | grep -w UUID | grep -v "$root_partition_device")

	# write information to log
	echo -e "\nOld UUID:  ${root_uuid}" >> $logfile
	echo "SD UUID:   $sduuid" >> $logfile
	echo "SATA UUID: $satauuid" >> $logfile
	echo "eMMC UUID: $emmcuuid $eMMCFilesystemChoosen" >> $logfile
	echo "Boot: \$1 $1 $eMMCFilesystemChoosen" >> $logfile
	echo "Root: \$2 $2 $FilesystemChoosen" >> $logfile

	# calculate usage and see if it fits on destination
	USAGE=$(df -BM | grep ^/dev | head -1 | awk '{print $3}' | tr -cd '[0-9]. \n')
	DEST=$(df -BM | grep ^/dev | grep ${TempDir}/rootfs | awk '{print $4}' | tr -cd '[0-9]. \n')
	if [[ $USAGE -gt $DEST ]]; then
		dialog --title "$title" --backtitle "$backtitle" --colors --infobox\
		"\n\Z1Partition too small.\Zn Needed: $USAGE MB Avaliable: $DEST MB" 5 60
		umountdevice "$1"; umountdevice "$2"
		exit 1
	fi

	if [[ $1 == *nand* ]]; then
		# creating nand boot. Copy precompiled uboot
		rsync -aqc $BOOTLOADER/* ${TempDir}/bootfs
	fi

	# write information to log
	echo "Usage: $USAGE" >> $logfile
	echo -e "Dest: $DEST\n\n/etc/fstab:" >> $logfile
	cat /etc/fstab >> $logfile
	echo -e "\n/etc/mtab:" >> $logfile
	grep '^/dev/' /etc/mtab | egrep -v "log2ram|folder2ram" | sort >> $logfile

	# stop running services
	echo -e "\nFiles currently open for writing:" >> $logfile
	lsof / | awk 'NR==1 || $4~/[0-9][uw]/' | grep -v "^COMMAND" >> $logfile
	echo -e "\nTrying to stop running services to minimize open files:\c" >> $logfile
	StopRunningServices "nfs-|smbd|nmbd|winbind|ftpd|netatalk|monit|cron|webmin|rrdcached" >> $logfile
	StopRunningServices "log2ram|folder2ram|postgres|mariadb|mysql|postfix|mail|nginx|apache|snmpd" >> $logfile
	pkill dhclient 2>/dev/null
	LANG=C echo -e "\n\nChecking again for open files:" >> $logfile
	lsof / | awk 'NR==1 || $4~/[0-9][uw]/' | grep -v "^COMMAND" >> $logfile

	# count files is needed for progress bar
	dialog --title " $title " --backtitle "$backtitle" --infobox "\n  Counting files ... few seconds." 5 60
	TODO=$(rsync -ahvrltDn --delete --stats --exclude-from=$EX_LIST / ${TempDir}/rootfs | grep "Number of files:"|awk '{print $4}' | tr -d '.,')
	echo -e "\nCopying ${TODO} files to $2. \c" >> $logfile

	# creating rootfs
	rsync -avrltD --delete --exclude-from=$EX_LIST / ${TempDir}/rootfs | nl | awk '{ printf "%.0f\n", 100*$1/"'"$TODO"'" }' \
	| dialog --backtitle "$backtitle" --title " $title " --gauge "\n\n  Transferring rootfs to $2 ($USAGE MB). \n\n \
	This will take approximately $(( $((USAGE/300)) * 5 )) minutes to finish. Please wait!\n\n" 11 80

	# run rsync again to silently catch outstanding changes between / and ${TempDir}/rootfs/
	dialog --title "$title" --backtitle "$backtitle" --infobox "\n  Cleaning up ... Almost done." 5 40
	rsync -avrltD --delete --exclude-from=$EX_LIST / ${TempDir}/rootfs >/dev/null 2>&1

	# creating fstab from scratch
	rm -f ${TempDir}/rootfs/etc/fstab
	mkdir -p ${TempDir}/rootfs/etc ${TempDir}/rootfs/media/mmcboot ${TempDir}/rootfs/media/mmcroot

	# Restore TMP and swap
	echo "# <file system>					<mount point>	<type>	<options>							<dump>	<pass>" > ${TempDir}/rootfs/etc/fstab
	echo "tmpfs						/tmp		tmpfs	defaults,nosuid							0	0" >> ${TempDir}/rootfs/etc/fstab
	grep swap /etc/fstab >> ${TempDir}/rootfs/etc/fstab

	# creating fstab, kernel and boot script for NAND partition
	#
	if [[ $1 == *nand* ]]; then
		echo "Finishing installation to NAND." >> $logfile
		REMOVESDTXT="and remove SD to boot from NAND"
		echo "$1 /boot vfat	defaults 0 0" >> ${TempDir}/rootfs/etc/fstab
		echo "$2 / ext4 defaults,noatime,nodiratime,commit=600,errors=remount-ro 0 1" >> ${TempDir}/rootfs/etc/fstab
		dialog --title "$title" --backtitle "$backtitle" --infobox "\nConverting kernel ... few seconds." 5 60
		mkimage -A arm -O linux -T kernel -C none -a "0x40008000" -e "0x40008000" -n "Linux kernel" -d \
			/boot/zImage ${TempDir}/bootfs/uImage >/dev/null 2>&1
		cp /boot/script.bin ${TempDir}/bootfs/

		if [[ $DEVICE_TYPE != a13 ]]; then
			# Note: Not using UUID based boot for NAND
			cat <<-EOF > ${TempDir}/bootfs/uEnv.txt
			console=ttyS0,115200
			root=$2 rootwait
			extraargs="console=tty1 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:0 consoleblank=0 loglevel=1"
			EOF
		else
			# Note: Not using UUID based boot for NAND
			cat <<-EOF > ${TempDir}/bootfs/uEnv.txt
			console=ttyS0,115200
			root=$2 rootwait
			extraargs="consoleblank=0 loglevel=1"
			EOF
		fi

		sync

		[[ $DEVICE_TYPE = a20 ]] && echo "machid=10bb" >> ${TempDir}/bootfs/uEnv.txt
		# ugly hack becouse we don't have sources for A10 nand uboot
		if [[ $ID == Cubieboard || $BOARD_NAME == Cubieboard || $ID == "Lime A10" || $BOARD_NAME == "Lime A10" ]]; then
			cp ${TempDir}/bootfs/uEnv.txt ${TempDir}/rootfs/boot/uEnv.txt
			cp ${TempDir}/bootfs/script.bin ${TempDir}/rootfs/boot/script.bin
			cp ${TempDir}/bootfs/uImage ${TempDir}/rootfs/boot/uImage
		fi
		umountdevice "/dev/nand"
		tune2fs -o journal_data_writeback /dev/nand2 >/dev/null 2>&1
		tune2fs -O ^has_journal /dev/nand2 >/dev/null 2>&1
		e2fsck -f /dev/nand2 >/dev/null 2>&1
	fi

	# Boot from eMMC, root = eMMC or SATA / USB
	#
	if [[ $2 == ${emmccheck}p* || $1 == ${emmccheck}p* ]]; then

		if [[ $2 == ${SDA_ROOT_PART} ]]; then
			local targetuuid=$satauuid
			local choosen_fs=$FilesystemChoosen
			echo "Finalizing: boot from eMMC, rootfs on USB/SATA." >> $logfile
			if [[ $eMMCFilesystemChoosen == "btrfs" ]]; then
				echo "$emmcuuid	/media/mmcroot  $eMMCFilesystemChoosen	${mountopts[$eMMCFilesystemChoosen]}" >> ${TempDir}/rootfs/etc/fstab
			fi
		else
			local targetuuid=$emmcuuid
			local choosen_fs=$eMMCFilesystemChoosen
			echo "Finishing full install to eMMC." >> $logfile
		fi

		# fix that we can have one exlude file
		cp -R /boot ${TempDir}/bootfs
		# old boot scripts
		sed -e 's,root='"$root_uuid"',root='"$targetuuid"',g' -i ${TempDir}/bootfs/boot/boot.cmd
		# new boot scripts
		if [[ -f ${TempDir}/bootfs/boot/armbianEnv.txt ]]; then
			sed -e 's,rootdev=.*,rootdev='"$targetuuid"',g' -i ${TempDir}/bootfs/boot/armbianEnv.txt
		else
			sed -e 's,setenv rootdev.*,setenv rootdev '"$targetuuid"',g' -i ${TempDir}/bootfs/boot/boot.cmd
			[[ -f ${TempDir}/bootfs/boot/boot.ini ]] && sed -e 's,^setenv rootdev.*$,setenv rootdev "'"$targetuuid"'",' -i ${TempDir}/bootfs/boot/boot.ini
			[[ -f ${TempDir}/rootfs/boot/boot.ini ]] && sed -e 's,^setenv rootdev.*$,setenv rootdev "'"$targetuuid"'",' -i ${TempDir}/rootfs/boot/boot.ini
		fi
		mkimage -C none -A arm -T script -d ${TempDir}/bootfs/boot/boot.cmd ${TempDir}/bootfs/boot/boot.scr	>/dev/null 2>&1 || (echo "Error"; exit 0)

		# fstab adj
		if [[ "$1" != "$2" ]]; then
			echo "$emmcbootuuid	/media/mmcboot	ext4    ${mountopts[ext4]}" >> ${TempDir}/rootfs/etc/fstab
			echo "/media/mmcboot/boot   				/boot		none	bind								0       0" >> ${TempDir}/rootfs/etc/fstab
		fi


		if [[ $eMMCFilesystemChoosen == "btrfs" ]]; then
			echo "$targetuuid	/		$choosen_fs	${mountopts[$choosen_fs]}" >> ${TempDir}/rootfs/etc/fstab
			# swap file not supported under btrfs but we might have made a partition
			[[ -n ${emmcswapuuid} ]] && sed -e 's,/var/swap.*,'$emmcswapuuid' 	none		swap	sw								0	0,g' -i ${TempDir}/rootfs/etc/fstab
			sed -e 's,rootfstype=.*,rootfstype='$eMMCFilesystemChoosen',g' -i ${TempDir}/bootfs/boot/armbianEnv.txt
		else
			sed -e 's,rootfstype=.*,rootfstype='$choosen_fs',g' -i ${TempDir}/bootfs/boot/armbianEnv.txt
			echo "$targetuuid	/		$choosen_fs	${mountopts[$choosen_fs]}" >> ${TempDir}/rootfs/etc/fstab
		fi

		if [[ $(type -t write_uboot_platform) != function ]]; then
			echo "Error: no u-boot package found, exiting"
			exit -1
		fi
		write_uboot_platform $DIR $emmccheck

	fi

	# Boot from SD card, root = SATA / USB
	#
	if [[ $2 == ${SDA_ROOT_PART} && -z $1 ]]; then
		echo -e "Finishing transfer to USB/SATA, boot from SD/eMMC" >> $logfile
		[[ -f /boot/boot.cmd ]] && sed -e 's,root='"$root_uuid"',root='"$satauuid"',g' -i /boot/boot.cmd
		[[ -f /boot/boot.ini ]] && sed -e 's,^setenv rootdev.*$,setenv rootdev "'"$satauuid"'",' -i /boot/boot.ini
		# new boot scripts
		if [[ -f /boot/armbianEnv.txt ]]; then
			sed -e 's,rootdev=.*,rootdev='"$satauuid"',g' -i /boot/armbianEnv.txt
			grep -q '^rootdev' /boot/armbianEnv.txt || echo "rootdev=$satauuid" >> /boot/armbianEnv.txt
			sed -e 's,rootfstype=.*,rootfstype='$FilesystemChoosen',g' -i /boot/armbianEnv.txt
			grep -q '^rootfstype' /boot/armbianEnv.txt || echo "rootfstype=$FilesystemChoosen" >> /boot/armbianEnv.txt
		else
			sed -e 's,setenv rootdev.*,setenv rootdev '"$satauuid"',' -i /boot/boot.cmd
			sed -e 's,setenv rootdev.*,setenv rootdev '"$satauuid"',' -i /boot/boot.ini
			sed -e 's,setenv rootfstype.*,setenv rootfstype '"$FilesystemChoosen"',' -i /boot/boot.cmd
			sed -e 's,setenv rootfstype.*,setenv rootfstype '"$FilesystemChoosen"',' -i /boot/boot.ini
		fi
		[[ -f /boot/boot.cmd ]] && mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr >/dev/null 2>&1 || (echo "Error"; exit 0)
		mkdir -p ${TempDir}/rootfs/media/mmc/boot
		echo "${sduuid}	/media/mmcboot	ext4    ${mountopts[ext4]}" >> ${TempDir}/rootfs/etc/fstab
		echo "/media/mmcboot/boot  				/boot		none	bind								0       0" >> ${TempDir}/rootfs/etc/fstab
		echo "$satauuid	/		$FilesystemChoosen	${mountopts[$FilesystemChoosen]}" >> ${TempDir}/rootfs/etc/fstab
		# recreate swap file if already existing (might be missing since zram only)
		if [ -f /var/swap ]; then
			fallocate -l 128M ${TempDir}/rootfs/var/swap || dd if=/dev/zero of=${TempDir}/rootfs/var/swap bs=1M count=128 status=noxfer
			mkswap ${TempDir}/rootfs/var/swap
		fi
	fi

	# Boot from SPI, root = SATA / USB
	#
	if [[ $1 == *spi* ]]; then
		sed -e 's,rootdev=.*,rootdev='"$satauuid"',g' -i ${TempDir}/rootfs/boot/armbianEnv.txt
		echo "$satauuid	/		$FilesystemChoosen	${mountopts[$FilesystemChoosen]}" >> ${TempDir}/rootfs/etc/fstab
	fi

	# recreate OMV mounts at destination if needed
	grep -q ' /srv/' /etc/fstab
	if [ $? -eq 0 -a -f /etc/default/openmediavault ]; then
		echo -e '# >>> [openmediavault]' >> ${TempDir}/rootfs/etc/fstab
		grep ' /srv/' /etc/fstab | while read ; do
			echo "${REPLY}" >> ${TempDir}/rootfs/etc/fstab
			mkdir -p -m700 "${TempDir}/rootfs$(awk -F" " '{print $2}' <<<"${REPLY}")"
		done
		echo -e '# <<< [openmediavault]' >> ${TempDir}/rootfs/etc/fstab
	fi

	echo -e "\nChecking again for open files:" >> $logfile
	lsof / | awk 'NR==1 || $4~/[0-9][uw]/' | grep -v "^COMMAND" >> $logfile
	LANG=C echo -e "\n$(date): Finished\n\n" >> $logfile
	cat $logfile >${TempDir}/rootfs${logfile}
	sync

	umountdevice "/dev/sda"
} # create_armbian


# Accept device as parameter: for example /dev/sda unmounts all their mounts
umountdevice()
{
	if [[ -n $1 ]]; then
		device=$1;
		for n in ${device}*; do
			if [[ $device != "$n" ]]; then
				if mount|grep -q ${n}; then
					umount -l $n >/dev/null 2>&1
				fi
			fi
		done
	fi
} # umountdevice

show_nand_warning()
{
	local temp_rc=$(mktemp)
	cat <<-'EOF' > $temp_rc
	screen_color = (WHITE,RED,ON)
	EOF
	local warn_text="You are installing the system to sunxi NAND.

	This is not recommended as NAND has \Z1worse performance
	and reliability\Zn than a good SD card.

	You have been warned."

	DIALOGRC=$temp_rc dialog --title "NAND warning" --backtitle "$backtitle" --colors \
		--ok-label "I understand and agree" --msgbox "$warn_text" 10 70
}

# formatting sunxi NAND - no parameters, fixed solution.
#
formatnand()
{
	[[ ! -e /dev/nand ]] && echo "NAND error" && exit 0

	show_nand_warning

	dialog --title "$title" --backtitle "$backtitle" --infobox "\nFormating ... up to one minute." 5 40
	if [[ $DEVICE_TYPE = a20 ]]; then
		(echo y;) | sunxi-nand-part -f a20 /dev/nand 65536 'bootloader 65536' 'linux 0' >> $logfile 2>&1
	else
		(echo y;) | sunxi-nand-part -f a10 /dev/nand 65536 'bootloader 65536' 'linux 0' >> $logfile 2>&1
	fi

	mkfs.vfat /dev/nand1 >> $logfile 2>&1
	mkfs.ext4 -qF /dev/nand2 >> $logfile 2>&1
}


# formatting eMMC [device] example /dev/mmcblk1 - one can select filesystem type
#
formatemmc()
{
	# choose and create fs
	IFS=" "
	BTRFS=$(grep -o btrfs /proc/filesystems)
	FilesystemTargets="1 ext4 2 ext3 3 ext2"
	[[ -n $BTRFS && `uname -r | grep '^4.' ` ]] && FilesystemTargets=$FilesystemTargets" 4 $BTRFS"
	FilesystemOptions=($FilesystemTargets)

	FilesystemCmd=(dialog --title "Select filesystem type for eMMC $1" --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
	FilesystemChoices=$("${FilesystemCmd[@]}" "${FilesystemOptions[@]}" 2>&1 >/dev/tty)

	[[ $? -ne 0 ]] && exit 1
	eMMCFilesystemChoosen=${FilesystemOptions[(2*$FilesystemChoices)-1]}

	# deletes all partitions on eMMC drive
	dd bs=1 seek=446 count=64 if=/dev/zero of=$1 >/dev/null 2>&1
	# calculate capacity and reserve some unused space to ease cloning of the installation
	# to other media 'of the same size' (one sector less and cloning will fail)
	QUOTED_DEVICE=$(echo "${1}" | sed 's:/:\\\/:g')
	CAPACITY=$(parted ${1} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", \$2 / ( 1024 / \$4 ))}")

	if [[ $CAPACITY -lt 4000000 ]]; then
		# Leave 2 percent unpartitioned when eMMC size is less than 4GB (unlikely)
		LASTSECTOR=$(( 32 * $(parted ${1} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 98 / 3200))}") -1 ))
	else
		# Leave 1 percent unpartitioned
		LASTSECTOR=$(( 32 * $(parted ${1} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 99 / 3200))}") -1 ))
	fi

	parted -s $1 -- mklabel msdos
	dialog --title "$title" --backtitle "$backtitle" --infobox "\nFormating $1 to $eMMCFilesystemChoosen ... please wait." 5 60
	# we can't boot from btrfs
	if [[ $eMMCFilesystemChoosen == "btrfs" ]]; then
		# check whether swap is currently defined and a new swap partition is needed
		grep -q swap /etc/fstab
		case $? in
			0)
				parted -s $1 -- mkpart primary $eMMCFilesystemChoosen 8192s 139263s
				parted -s $1 -- mkpart primary $eMMCFilesystemChoosen 139264s 401407s
				parted -s $1 -- mkpart primary $eMMCFilesystemChoosen 401408s ${LASTSECTOR}s
				partprobe $1
				mkfs.ext4 ${mkopts[ext4]} $1"p1" >> $logfile 2>&1
				mkswap $1"p2" >> $logfile 2>&1
				mkfs.btrfs $1"p3" ${mkopts[$eMMCFilesystemChoosen]} >> $logfile 2>&1
				emmcbootuuid=$(blkid -o export $1"p1" | grep -w UUID)
				emmcswapuuid=$(blkid -o export $1"p2" | grep -w UUID)
				emmcuuid=$(blkid -o export $1"p3" | grep -w UUID)
				dest_root=$emmccheck"p3"
				;;
			*)
				parted -s $1 -- mkpart primary $eMMCFilesystemChoosen 8192s 139263s
				parted -s $1 -- mkpart primary $eMMCFilesystemChoosen 139264s ${LASTSECTOR}s
				partprobe $1
				mkfs.ext4 ${mkopts[ext4]} $1"p1" >> $logfile 2>&1
				mkfs.btrfs $1"p2" ${mkopts[$eMMCFilesystemChoosen]} >> $logfile 2>&1
				emmcbootuuid=$(blkid -o export $1"p1" | grep -w UUID)
				emmcuuid=$(blkid -o export $1"p2" | grep -w UUID)
				dest_root=$emmccheck"p2"
				;;
		esac
	else
		parted -s $1 -- mkpart primary $eMMCFilesystemChoosen 8192s ${LASTSECTOR}s
		partprobe $1
		mkfs.${eMMCFilesystemChoosen} ${mkopts[$eMMCFilesystemChoosen]} $1"p1" >> $logfile 2>&1
		emmcuuid=$(blkid -o export $1"p1" | grep -w UUID)
		emmcbootuuid=$emmcuuid
	fi


}


# formatting SATA/USB [device] example /dev/sda3
#
formatsata()
{
	# choose and create fs
	IFS=" "
	ROOTFSTYPE=$(lsblk -o MOUNTPOINT,FSTYPE | awk -F" " '/^\/\ / {print $2}')
	case ${ROOTFSTYPE} in
		btrfs)
			FilesystemTargets="1 btrfs"
			;;
		*)
			BTRFS=$(grep -o btrfs /proc/filesystems)
			FilesystemTargets="1 ext4 2 ext3 3 ext2"
			[[ -n $BTRFS && `uname -r | grep '^4.' ` && $choice != 6 ]] && FilesystemTargets=$FilesystemTargets" 4 $BTRFS"
			;;
	esac
	FilesystemOptions=($FilesystemTargets)

	FilesystemCmd=(dialog --title "Select filesystem type for $1" --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
	FilesystemChoices=$("${FilesystemCmd[@]}" "${FilesystemOptions[@]}" 2>&1 >/dev/tty)

	[[ $? -ne 0 ]] && exit 1
	FilesystemChoosen=${FilesystemOptions[(2*$FilesystemChoices)-1]}

	dialog --title "$title" --backtitle "$backtitle" --infobox "\nFormating $1 to $FilesystemChoosen ... please wait." 5 60
	mkfs.${FilesystemChoosen} ${mkopts[$FilesystemChoosen]} $1 >> $logfile 2>&1
}


# choose target SATA/USB partition.
checksatatarget()
{
	IFS=" "
	SataTargets=$(awk '/sd/ {print "/dev/"$4}' </proc/partitions | grep -E '[0-9]{1,4}' | nl | xargs echo -n)
	if [[ -z $SataTargets ]]; then
		dialog --title "$title" --backtitle "$backtitle" --colors --msgbox \
		"\n\Z1There are no avaliable partitions. Please create them.\Zn" 7 60
		fdisk /dev/$satacheck
	fi
	SataTargets=$(awk '/sd/ {print "/dev/"$4}' </proc/partitions | grep -E '[0-9]{1,4}' | nl | xargs echo -n)
	SataOptions=($SataTargets)

	SataCmd=(dialog --title "Select destination:" --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
	SataChoices=$("${SataCmd[@]}" "${SataOptions[@]}" 2>&1 >/dev/tty)

	[[ $? -ne 0 ]] && exit 1
	SDA_ROOT_PART=${SataOptions[(2*$SataChoices)-1]}
}


# show warning [TEXT]
ShowWarning()
{
	dialog --title "$title" --backtitle "$backtitle" --cr-wrap --colors --yesno " \Z1$(toilet -f mono12 WARNING)\Zn\n$1" 17 74
	[[ $? -ne 0 ]] && exit 1
}

# try to stop running services
StopRunningServices()
{
	systemctl --state=running | awk -F" " '/.service/ {print $1}' | sort -r | \
		egrep -e "$1" | while read ; do
		echo -e "\nStopping ${REPLY} \c"
		systemctl stop ${REPLY} 2>&1
	done
}

main()
{
	export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

	# This tool must run under root
	if [[ $EUID -ne 0 ]]; then
		echo "This tool must run as root. Exiting ..." >&2
		exit 1
	fi

	# Check if we run it from SD card
	# TODO: Disable/remove this in the future
	case ${root_partition_device} in
		/dev/mmcblk*) # mmc device, we can continue
			:
			;;
		*)
			dialog --title "$title" --backtitle "$backtitle" --colors --infobox "\n\Z1This tool must run from SD-card! \Zn" 5 37
			exit 1
			;;
	esac

	[ -f $logfile ] && echo -e "\n\n\n" >> $logfile
	LANG=C echo -e "$(date): Start ${0##*/}.\n" >> $logfile

	IFS="'"
	options=()
	if [[ -n $emmccheck ]]; then
		ichip="eMMC";
		dest_boot=$emmccheck"p1"
		dest_root=$emmccheck"p1"
	else
		ichip="NAND"
		dest_boot="/dev/nand1"
		dest_root="/dev/nand2"
	fi


	[[ -n $nandcheck || -n $emmccheck ]] && options+=(1 "Boot from $ichip - system on $ichip")
	[[ ( -n $nandcheck || -n $emmccheck ) && -n $satacheck ]] && options+=(2 "Boot from $ichip - system on SATA or USB")
	[[ -n $satacheck ]] && options+=(3 "Boot from SD   - system on SATA or USB")
	[[ ( $LINUXFAMILY == odroidxu4 || $LINUXFAMILY == mvebu* ) && ( -b /dev/mmcblk0boot0 || -b /dev/mmcblk1boot0 ) ]] && options+=(4 "Update the bootloader on a special eMMC partition")
	[[ $(type -t write_uboot_platform_mtd) == function && -b /dev/mtd0 && -f /usr/sbin/flashcp ]] && options+=(5 "Install the bootloader to SPI Flash")
	[[ -n $spicheck ]] && options+=(6 "Boot from SPI  - system on SATA or USB")
	[[ ${#options[@]} -eq 0 || "$root_uuid" == "$emmcuuid" || "$root_uuid" == "/dev/nand2" ]] && \
	dialog --title "$title" --backtitle "$backtitle" --colors --no-collapse --msgbox "\n\Z1There are no targets. Please check your drives.\Zn" 7 54
	cmd=(dialog --title "Choose an option:" --backtitle "$backtitle" --menu "\nCurrent root: $root_uuid \n \n" 14 60 7)
	choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
	[[ $? -ne 0 ]] && exit 1

	for choice in $choices
	do
		case $choice in
			1)
				title="$ichip install"
				command="Power off"
				ShowWarning "This script will erase your $ichip. Continue?"
				if [[ -n $emmccheck ]]; then
					umountdevice "$emmccheck"
					formatemmc "$emmccheck"
				else
					umountdevice "/dev/nand"
					formatnand
				fi
				create_armbian "$dest_boot" "$dest_root"
				umount ${TempDir}/rootfs
				umount ${TempDir}/bootfs
				;;
			2)
				title="$ichip boot | USB/SATA root install"
				command="Power off"
				checksatatarget
				ShowWarning "This script will erase your $ichip and $SDA_ROOT_PART. Continue?"
				if [[ -n $emmccheck ]]; then
					umountdevice "$emmccheck"
					formatemmc "$emmccheck"
					else
					umountdevice "/dev/nand"
					formatnand
				fi
				umountdevice "${SDA_ROOT_PART//[0-9]*/}"
				formatsata "$SDA_ROOT_PART"
				create_armbian "$dest_boot" "$SDA_ROOT_PART"
				umount ${TempDir}/rootfs
				umount ${TempDir}/bootfs
				;;
			3)
				title="MMC (SD/eMMC) boot | USB/SATA root install"
				command="Reboot"
				checksatatarget
				ShowWarning "This script will erase your device $SDA_ROOT_PART. Continue?"
				formatsata "$SDA_ROOT_PART"
				create_armbian "" "$SDA_ROOT_PART"
				;;
			4)
				if [[ -b /dev/mmcblk0boot0 ]]; then
					BOOTPART="/dev/mmcblk0"
				elif [[ -b /dev/mmcblk1boot0 ]]; then
					BOOTPART="/dev/mmcblk1"
				fi
				ShowWarning "This script will update the bootloader on $BOOTPART. Continue?"
				write_uboot_platform $DIR $BOOTPART
				echo "Done"
				return
				;;
			5)
				# TODO: Add warning dialogs with MTD device info
				write_uboot_platform_mtd $DIR /dev/mtd0
				echo "Done"
				return
				;;
			6)
				# Espressobin has flash boot by default
				title="SPI flash boot | USB/SATA root install"
				command="Power off"
				# we need to copy boot
				sed -i '/boot/d' $EX_LIST
				checksatatarget
				ShowWarning "This script will erase your device $SDA_ROOT_PART. Continue?"
				formatsata "$SDA_ROOT_PART"
				create_armbian "spi" "$SDA_ROOT_PART"
				;;
		esac
	done

	dialog --title "$title" --backtitle "$backtitle" --yes-label "$command" --no-label "Exit" --yesno "\nAll done. $command $REMOVESDTXT" 7 70
	[[ $? -eq 0 ]] && "$(echo ${command,,} | sed 's/ //')"
} # main

main "$@"
